package com.thread.thread.Lua;

import com.google.common.collect.Lists;
import com.google.common.io.Files;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Component;

import java.io.File;
import java.nio.charset.Charset;
import java.util.Collections;
// eval "local key = KEYS[1]   local current = tonumber(redis.call('get', key) or '0')  redis.call('INCRBY', key,'1')  redis.call('expire', key,'2')  return current"  1 0

//此命令可直接在redis的客户端执行，key的过期时间为两秒,进入一次将当前的key加1，两秒后变0，业务可根据这个值知道此时有多少正在占用
@Component
public class RedisLock {
	@Autowired
	RedisTemplate redisTemplate;

	private static final Long SUCCESS = 1L;

	/**
		* 获取锁
     *
	 * @param lockKey       redis的key
     * @param limit      redis的value要求是随机串，防止释放其他请求的锁
     * @return
			 */
	public  boolean lock(String lockKey, String limit) throws Exception{
		ClassPathResource classPathResource = new ClassPathResource("limit.lua");

		String luaScript = Files.toString(classPathResource.getFile(), Charset.defaultCharset());

		//<>里面为返回值的类型
		RedisScript<Long> redisScript = new DefaultRedisScript<>(luaScript, Long.class);

		//对非string类型的序列化
		redisTemplate.setKeySerializer(new StringRedisSerializer());
		redisTemplate.setValueSerializer(new StringRedisSerializer());

		Object result = redisTemplate.execute(redisScript,Lists.newArrayList(lockKey),  limit);
		System.out.println("redis返回结果"+result);
		return SUCCESS.equals(result);
	}
	/**
	 * 释放锁
	 *
	 * @param lockKey   redis的key
	 * @param value     redis的value  只有value比对一致，才能确定是本请求 加的锁 才能正常释放
	 * @return
	 */
	public  boolean unlock(String lockKey, String value) {

		String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";

		RedisScript<String> redisScript = new DefaultRedisScript<>(script, String.class);

		try {
			Object result = redisTemplate.execute(redisScript, Collections.singletonList(lockKey), value);
			if (SUCCESS.equals(result)) {
				return true;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}


}
